package org.moonlight.jvm.rtda.share.heap.symref;

import org.moonlight.jvm.rtda.share.heap.Class;
import org.moonlight.jvm.rtda.share.methodarea.RtConstantPool;

import java.io.Serializable;

/**
 * 符号引用 - 所谓符号引用就是类似于类的全限定名一样的玩意，通过这个玩意可以定位到一个类或者一个方法或者一个字段。
 *          那么在解析符号引用的时候，就是根据这个全限定名，找到这个类解析出来的 {@link org.moonlight.jvm.rtda.share.heap.Class}
 *          在内存的哪个位置。
 *          对于类符号引用，只要有类名，就可以解析符号引用。对于字段，首先要解析类符号引用得到类数据，然后用字段名和描述符查找字段数据。
 *          方法符号引用的解析过程和字段符号引用类似。
 *
 * @author Moonlight
 * @createTime 2023/8/29 17:46
 **/
public class SymRef implements Serializable {

    /** 符号引用所属的运行时常量池 **/
    protected RtConstantPool rtCp;
    /** 所属类型的全限定名 todo ??? **/
    protected String className;
    /** 所属类型的Class对象 todo ??? **/
    protected Class clazz;

    /**
     * 根据 类的符号引用 解析出 {@link Class} 类对象
     * 如果类符号引用已经解析，则直接返回类指针。
     * 如果 类D 通过 符号引用N 引用了 类C 的话，要解析N，先用D的类加载器加载C，然后检查D是否有权限访问C，如果没有，则抛出IllegalAccessError异常。
     *
     * @return {@link Class} 类对象
     * @createTime 11:20 2023/8/30
     * @author moonlight
     **/
    public Class resolvedClass() {
        if (this.clazz != null) {
            return this.clazz;
        }
        Class d = this.rtCp.getClazz();
        Class c = d.getLoader().loadClass(this.className);
        if (!c.isAccessibleTo(d)) {
            System.out.println("java.lang.IllegalAccessError");
        }
        this.clazz = c;
        return this.clazz;
    }

}
